package main

import (
	"encoding/hex"
	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"strings"
)

func main() {
	//gin init
	gin.SetMode(gin.ReleaseMode)
	g := gin.Default()
	g.GET("/api/v1/iap/get_firmware_info",FirmwareInfo)
	g.POST("/api/v1/iap/get_firmware_info",FirmwareInfo)
	g.GET("/api/v1/iap/get_firmware",Firmware)
	g.POST("/api/v1/iap/get_firmware",Firmware)
	log.Info("iap serve start success")
	if err := g.Run(":9000");err != nil{
		log.Panic(err)
	}
}

func FirmwareInfo(c *gin.Context)  {
	logger := log.WithFields(log.Fields{"fn":"FirmwareInfo","sn":c.Query("sn")})

	version := c.Query("version")
	if version ==""{
		version = getLatestFirmware()
		logger.Info("no version params,use latest version:",version)
	}else{
		logger.Info("version:",version)
	}
	fileName := version+".bin"
	size,err := getFirmwareSize(fileName)
	if err !=nil{
		version = getLatestFirmware()
		logger.Info("this version no exit,use latest version:",version)
		fileName = version+".bin"
	}
	if err !=nil{
		c.JSON(http.StatusBadRequest,gin.H{"err":err.Error()})
	}else{
		c.JSON(http.StatusOK, gin.H{"version":version,"size":size})
	}
}

func Firmware(c *gin.Context)  {
	logger := log.WithFields(log.Fields{"fn":"Firmware","sn":c.Query("sn")})

	version := c.Query("version")
	 encode := c.Query("encode")
	addr,_ :=  strconv.Atoi(c.Query("addr"))
	size,_ := strconv.Atoi(c.Query("size"))

	logger.Info("version:",version,"  addr:",addr," , size:",size)
	fileName := version+".bin"
	bs,err :=getFirmwareBytes(fileName, uint32(addr), uint32(size))
	if err != nil{
		c.JSON(http.StatusBadRequest,gin.H{"err":err.Error()})
	}else {
        if encode =="hex"{
			c.Data(http.StatusOK, "application/octet-stream", []byte(hex.EncodeToString(bs)))
		}else{
			c.Data(http.StatusOK, "application/octet-stream", bs)
		}
	}
}

/*获取最新的固件版本号*/
func getLatestFirmware() string {
	files, _ := ioutil.ReadDir("./firmware/")
	latestFirmware :=""
	for _,file := range files{
		if strings.Compare(file.Name(),latestFirmware)>0{
			latestFirmware = file.Name()
		}
	}
	return strings.Replace(latestFirmware,".bin","",-1)
}

/*获取文件大小*/
func getFirmwareSize(fileName string)(uint32,error) {
	fi,err:=os.Stat("./firmware/"+fileName)
	if err !=nil{
		return 0, err
	}
	return uint32(fi.Size()),nil
}

/*获取文件片段字节*/
func getFirmwareBytes(fileName string,addr,size uint32) ([]byte,error) {
	file,err:=os.Open("./firmware/"+fileName)
	if err !=nil{
		return nil, err
	}
	defer file.Close()

	buf := make([]byte,size)
	_,err =file.ReadAt(buf, int64(addr))
	if err !=nil{
		return nil, err
	}
	return buf,nil
}